--love.filesystem.setRequirePath("?.lua;?/init.lua;main/?.lua;main/?/init.lua")

local Runner     = require("main.runner")
local BOXUI = require("boxui")

-- extra modules
BOXUI.require("main.lexer") -- used by codeviewer
BOXUI.require("main.codeviewer")
BOXUI.require("main.filelist")
BOXUI.require("main.logger")

-- standard
local utils = BOXUI.utils
local Container = BOXUI.container
local Panel     = BOXUI.panel
local List      = BOXUI.list
local Button    = BOXUI.button
local Slider    = BOXUI.slider

-- extra
local Codeviewer = BOXUI.codeviewer
local Filelist   = BOXUI.filelist
local Logger     = BOXUI.logger


local fl  -- filelist
local cv  -- codeviewer
local opl -- option list
local log -- log list
local mgr -- manager

local ASSETS_DIR = "main/assets/"

local addIcon = function(t, icon)
	if type(icon) == "table" then
		for i, v in ipairs(icon) do
			t[v] = love.graphics.newImage(ASSETS_DIR .. v .. ".png")
		end
		return
	end
	t[icon] = love.graphics.newImage(ASSETS_DIR .. icon .. ".png")
end

local icons = {}
addIcon(icons, {"folder", "file", "credits", "run", "clear", "copy", "help",
	"warn", "ok"})

local cursor = love.mouse.newCursor( ASSETS_DIR .. 'cursor.png', 7, 7 )

local EXTS = {["lua"] = true, ["txt"] = true}
local INFOFILE_NAME = "info.txt"
local DEFAULT_INFOFILE = "examples/info.txt"
local DEFAULT_DIR = "examples"

local fl_onClick = function(item)
	local ctx = item.context
	if not ctx then return end
	local activeFile = nil
	if ctx.type == "directory" then
		fl:setPath(ctx.name)
		if fl.path:find(DEFAULT_DIR, 1, true) == 1 then
			local fname = fl.path .. '/' .. INFOFILE_NAME
			local info = love.filesystem.getInfo(fname)
			if info and info.type == "file" then activeFile = fname
			else activeFile = DEFAULT_INFOFILE end
		else
			activeFile = cv.filename
		end
	elseif ctx.type == "file" then
		activeFile = ctx.name
	end
	if cv.filename ~= activeFile then
		cv:loadFile(activeFile, true)
		log:add("Loaded: " .. cv.filename)
	elseif ctx.type == "file" then
		log:add("Already loaded: " .. cv.filename, "warn")
	end
end

local oplOn = {}

local loveCalls


local opl_onRun = function()
	local filename, ext = cv.filename, cv.extension
	if not filename or ext ~= "lua" or filename:find(DEFAULT_DIR, 1, true) ~= 1 then
		log:add("Cannot run " .. (filename or "nothing"), "warn")
		return
	end
	Runner.run(filename, loveCalls, filename:match("(.-/?)[^/]*$"))
end

local opl_onClear = function()
	if cv.filename == nil then
		log:add("Nothing to be cleared", "warn")
		return
	end
	log:add("Cleared: " .. cv.filename)
	cv:clear()
end

local opl_onCopy = function()
	if not cv.filename then
		log:add("Nothing to be copied", "warn")
		return
	end
	love.system.setClipboardText(love.filesystem.read(cv.filename))
	log:add("Copied to clipboard: " .. cv.filename)
end

local _opl_onFile = function(filename)
	if filename == cv.filename then
		log:add("Already loaded: " .. cv.filename, "warn")
		return
	end
	cv:loadFile(filename, true)
	log:add("Loaded: " .. cv.filename)
end

local opl_onCredits = function()
	_opl_onFile("main/text/credits.txt")
end

local opl_onHelp = function()
	_opl_onFile("main/text/help.txt")
end

local opl_onLog = function(item)
	local found = mgr:find(log)
	local mgrobjects = mgr.objects
	if found then
		mgr:remove(found)
		item.icon = icons.warn
	else
		mgr:insert(log)
		item.icon = icons.ok
	end
	opl.list:redraw()
end

local opl_items = {
	{text = "Run",     context = opl_onRun,     icon = icons.run},
	{text = "Clear",   context = opl_onClear,   icon = icons.clear},
	{text = "Copy",    context = opl_onCopy,    icon = icons.copy},
	{text = "Help",    context = opl_onHelp,    icon = icons.help},
	{text = "Credits", context = opl_onCredits, icon = icons.credits},
	{text = "Log",     context = opl_onLog,     icon = icons.warn},
}

local opl_onClick = function(item)
	local fn = item.context
	if fn then fn(item) end
end


love.load = function()
	local smallfont  = love.graphics.newFont(10)
	local normalfont = love.graphics.newFont(12)
	local bigfont    = love.graphics.newFont(14)
	-- if we keep it nil, it resets love2d instead of restoring
	-- loveCalls = Runner.backupCallbacks() 
	love.graphics.setBackgroundColor(0.0, 0.1, 0.2)
	love.mouse.setCursor(cursor)
	
	fl = Filelist.new(10, 10, 180, 420)
	utils.addprops(fl, {
		hasHandle = true, hasShade = true, movable = true,
		diricon = icons["folder"], fileicon = icons["file"],
		extensions = EXTS
	})
	utils.addprops(fl.list, {font = normalfont, onClick = fl_onClick})
	fl:setPath(DEFAULT_DIR)

	opl = List.new(10, 440, 180, 200)
	utils.addprops(opl, {title = "Menu", wrapVert = true})
	utils.addprops(opl.list, {font = normalfont, onClick = opl_onClick})
	
	opl:setItems(opl_items)
	opl:refresh(true)
	opl.y = 590 - opl.height

	cv = Codeviewer.new(15, 15, 500, 420)
	cv.wrapVert = true
	cv.scalable = true
	cv:loadFile("main/text/help.txt")
	cv:refresh(true)
	
	--[[]]
	local test = Container.new(200, 25, 590, 500, List.template_theme)
	test.scalable = true
	local panel = Panel.new(0,0,586, 476)
	local button1 = Button.new(10, 10, 100, 30)
	local button2 = Button.new(10, 50, 100, 30)
	local button3 = Button.new(10, 90, 100, 30)
	local radiogroup = {button1, button2, button3}
	for k,v in pairs(radiogroup) do
		v.radiogroup = radiogroup
		panel:insert(v)
	end
	
	local slider1 = Slider.new(10, 130, 120, 30)
	slider1:refresh()
	panel:insert(slider1)

	local slider2 = Slider.new(140, 130, 30, 120)
	slider2.vertical = true
	slider2:refresh()
	panel:insert(slider2)
	
	panel:insert(cv)
	cv.theme = utils.freshenprops(utils.deepcopy(BOXUI.theme), {
		itemBack = cv.scheme.back, itemPadVert = 1,
		--itemForeActive = cv.scheme.activeline,
		borderBack = cv.scheme.padding,
		itemHeight = cv.fonts["big"]:getHeight() + 2
	})
	cv.list.theme = cv.theme
	
	test.hasHandle = true; test.hasShade = true; test.movable = true;
	--test.canvas = nil
	test.content = panel
	--cv.parent = test
	cv.hasHandle = true; cv.movable = true; cv.hasExpand = true; cv.hasShade = true;
	cv:refresh(true)
	test:refresh(true)
	--[[]]

	log = Logger.new(200, 540, 590, 200)
	utils.addprops( log, { hasHandle = true, hasShade = true, movable = true,
		title = "Log Window", wrapVert = false, wrapHori = false,
		slideDown = true, icons = icons})
	log.list.font = smallfont
	log.list.theme = utils.freshenprops(utils.deepcopy(BOXUI.theme), {
		itemBack = {.9,.9,1}, itemPadVert = 1,
		itemFore = {0,0,1}, itemForeActive = {1,.1,.1},
		--borderBack = cv.scheme.padding,
		itemHeight = smallfont:getHeight() + 2
	})
	log:add("Hello", "warn")
	mgr = Panel.new()
	mgr:insert(fl)
	mgr:insert(opl)
	mgr:insert(test)
end

love.wheelmoved = function(x, y)
	mgr:wheelmoved(x, y)
end

love.mousemoved = function(x, y, dx, dy)
	mgr:mousemoved(x, y, dx, dy)
end

love.mousepressed = function(x, y, button)
	mgr:mousepressed(x, y, button)
end

love.mousereleased = function(x, y, button)
	mgr:mousereleased(x, y, button)
end

love.update = function(dt)
	mgr:update(dt)
end

love.draw = function()
	love.graphics.setColor(1, 1, 1)
	mgr:draw()
	love.graphics.setColor(0, 0, 1)
	love.graphics.rectangle("fill", 0, 0, 40, 20)
	love.graphics.setColor(1, 1, 1)
	love.graphics.print(love.timer.getFPS(), 0, 0)

end

local mountno = 1
local mounted = {}
love.directorydropped = function(path)
	if not mounted[path] then
		local mountpoint = ("%s/ext_%0.2i"):format(DEFAULT_DIR, mountno)
		local appendToPath = false
		local success = love.filesystem.mount(path, mountpoint, appendToPath)
		if not success then
			log:add("Cannot mount " .. (path or "nothing"))
			return
		end
		mounted[path] = mountpoint
		mountno = mountno + 1
		log:add("Mounted: " .. path .. " to " .. mountpoint)
	end
	fl:setPath(mounted[path])
end

